﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.InteropServices.ComTypes;

using CSFileController.Exceptions;

namespace CSFileController.Classes
{
    internal class FileOperator
    {
        private FileStream fileStream;
        private BufferedStream bufferedStream;

        private byte[] buffer;

        public FileOperator(string path)
        {
            if (path == null || path.Equals(""))
                throw new ArgumentNullException("path");
            
            this.fileStream = new FileStream(path, FileMode.Open);
            this.bufferedStream = new BufferedStream(fileStream);

            int topBuffer = 0;
            int readLength = 1024;
            buffer= new byte[fileStream.Length+readLength*2];
            while(fileStream.Read(buffer, topBuffer, readLength) > 0 )
            {
                topBuffer += readLength;
            }
        }


        /// <summary>
        /// 删除指定路径文件的注释（仅“//”）（将buffer[]的注释内容全部换为0）
        /// </summary>
        public void deleteComment()
        {
            for(int i=0;i<fileStream.Length;i++)
            {
                if (buffer[i] == '/'&& buffer[i+1] == '/')
                {
                    int priorPos = i-1;
                    while (priorPos >= 0 && (char)buffer[priorPos] == ' ')
                        buffer[priorPos--] = 0;
                    while (buffer[i] != '\n')
                    {
                        buffer[i] = 0;
                        i++;
                    }
                    buffer[i] = 0;
                }
            }
        }

        /// <summary>
        /// 删除指定路径文件的空白行
        /// （将将buffer[]连续的多个换行符设置为 0 ）（换行符为“\r\n”）
        /// </summary>
        public void deleteBlankLine() 
        {
            bool get = false;
            for(int i = 0; i < fileStream.Length; i++)
            {
                if (i == 0 && (char)buffer[0] == '\r' && (char)buffer[1] == '\n')
                {
                    buffer[0] = 0;
                    buffer[1] = 0;
                    get = true;
                    i += 2;
                    continue;
                }
                while (i < fileStream.Length && buffer[i] == ' ') i++;
                if ((char)buffer[i] == '\n'&& (char)buffer[i-1] == '\r')
                    if (get)
                    {
                        buffer[i - 1] = 0;
                        buffer[i] = 0;
                    }
                    else
                        get = true;
                else
                {
                    if ((char)buffer[i] != '\r')
                        get = false;
                }
            }
        }

        /// <summary>
        /// 返回指定路径文件的单词数
        /// </summary>
        /// <returns></returns>
        public long countWord()
        {
            long count = 0;
            bool get = false;
            for(int i = 0;i<= fileStream.Length; i++)
            {
                if (get && i == fileStream.Length)
                    count++;
                else if (!get && isEnglishCharacter((char)buffer[i]))
                    get = true;
                else if (get && !isEnglishCharacter((char)buffer[i]))
                {
                    count ++;
                    get = false;
                }
            }
            return count;
        }

        private bool isEnglishCharacter(char ch)
        {
            if ((int)ch >= 65 && (int)ch <= 90)
                return true;
            if ((int)ch >= 97 && (int)ch <= 122)
                return true;
            return false;
        }

        /// <summary>
        /// 返回指定路径文件的行数
        /// </summary>
        /// <returns></returns>
        public int countLine()
        {
            int count = 1;
            for( int i = 0; i < fileStream.Length; i++)
            {
                if ((char)buffer[i] == '\n')
                    count++;
            }
            return count;
        }

        /// <summary>
        /// 删除buffer[]中值为0的元素，生成可直接被写入文件流的byte[]数组
        /// </summary>
        /// <returns></returns>
        private long updateBuffer()
        {
            int skip = 0;
            for(int i = 0; i < fileStream.Length; i++)
            {
                if (i + skip < fileStream.Length)
                {
                    while (i + skip < fileStream.Length && buffer[i + skip] == 0) 
                    {
                        skip++;
                    }
                    buffer[i] = buffer[i + skip];
                }
                else
                    buffer[i] = 0; 
            }
            return fileStream.Length - skip;
        }

        /// <summary>
        /// 根据输入的文件名，生成写入文件流，若非.cs文件，将抛出异常
        /// 包括写入原文件、写入同目录下其他现有文件、写入同目录下的新文件三种情况
        /// </summary>
        /// <param name="name"></param>
        /// <param name="tgtStream"></param>
        /// <param name="bfStream"></param>
        /// <param name="isNewFile"></param>
        private void getTargetStream(string name, out FileStream tgtStream, out BufferedStream bfStream, out bool isNewFile)
        {
            if (name.Length <= 3 || !name.Substring(name.Length - 3, 3).Equals(".cs"))
                throw new FileTypeException(".cs");
            
            if (name.Equals(Path.GetFileName(fileStream.Name)))
            {
                bfStream = bufferedStream;
                tgtStream = fileStream;
                isNewFile = false;
            }
            else
            {
                string path = Path.GetDirectoryName(fileStream.Name) + "\\" + name;
                if (Directory.Exists(path))
                    tgtStream = new FileStream(path, FileMode.Open);
                else
                    tgtStream = new FileStream(path, FileMode.Create);
                bfStream = new BufferedStream(tgtStream);
                isNewFile = true;
            }
        }

        /// <summary>
        /// 启动写文件行为，将buffer[]中的信息写入文件
        /// </summary>
        /// <param name="name"></param>
        public void write(string name)
        {
            long bufferSize = updateBuffer();

            FileStream stream = null;
            BufferedStream bfStream = null;
            bool isNewFile = false;

            getTargetStream(name, out stream, out bfStream, out isNewFile);
            
            if (stream == null || bfStream == null)
                return;

            stream.SetLength(0);

            //Write函数单词写入长度为int类型，长度可能不足，因此采用多次写入
            int writeLength = 2048;
            byte[] buffertemp = new byte[writeLength];
            long offset = 0;
            while (offset< bufferSize)
            {
                int length=(writeLength<bufferSize - offset)?writeLength:(int)(bufferSize-offset);
                for(int i = 0; i<length; i++)
                    buffertemp[i]= buffer[offset+i];
                stream.Write(buffertemp,0, length);
                offset += writeLength;
            }
            stream.Flush();

            if(isNewFile)
            {
                bfStream.Close();
                stream.Close();
            }
        }

        public void close()
        {
            fileStream.Close();
            bufferedStream.Close();
        }
    }
}
